import 'reflect-metadata'
import {parseScript} from 'esprima'
class IndexService{

    log(){
        console.log(231);
    }
}

const Types={
    "IndexService":Symbol.for("IndexService")
}

function inject(serviceIdentifier:Symbol) {
    
    return (target:object,targetKey:string,index:number)=>{

        if(!targetKey){
            Reflect.defineMetadata(targetKey,new IndexService(),target);
        }
        
    }
}

function  getParams(fn:Function) {
    let ast = parseScript(fn.toString());
    let funcParams:any[]=[];
    let node =ast.body[0];
    if(node.type=="FunctionDeclaration"){
        funcParams=node.params;
    }
    let validParams:string[]=[];
    funcParams.forEach(obj=>{
        if(obj.type=="Identifier"){
            validParams.push(obj.name);
        }
    })
    return validParams;
}


function controller<T extends {new (...args:any):{}}>(constructor:T) {
    
    class Controller extends constructor{
        constructor(...args:any){
            super(args);
           let params= getParams(constructor);
           console.log(params);
            let  identify :string;
           for ( identify of params) {
               this[identify]=Reflect.getMetadata(Types[identify],constructor)
           }
           
        }
    }
    return Controller
}

function Inject(): (_constructor: any, propertyName: string,index:any,t:any) => any {
    return function (_constructor: any, propertyName: string,index:any): any {
      const  propertyType: any = Reflect.getMetadata('design:type', _constructor, propertyName);
      _constructor[propertyName] =  new IndexService();
  
      return (_constructor as any)[propertyName];
    };
  }
  function validate<T>(target: any, propertyKey: string) {
    const  propertyType: any = Reflect.getMetadata('design:type', target, propertyKey);
    target[propertyKey] =  new IndexService();
    
}

@controller
class IndexController{
@validate
private t:IndexService

constructor( @inject(Types.IndexService) private server?:IndexService){

    }
    log(){
        this.t.log();
        this.server.log();
    }
}


new IndexController().log();
